package analyseApplets;

import graph.SimpleGridGraph;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.Vector;

import analyses.DepthAnalyser2D;
import analyses.Dijkstra;
import analyses.ViewAnalyserGrid;

import processing.core.PApplet;
import processing.core.PGraphics;
import processing.core.PImage;
import simpleGeom.Bounds2D;

public class ViewAnalyseApplet extends PApplet {
	PImage dataImage;//obstacles
	PImage walkImage;//walkBorders
	//PImage analyseImage;
	PImage backgroundView;//viewPositions
	PImage backgroundPos;//startPoints
	public Dijkstra dijkstra;
	ArrayList<Integer> path;
	int startX;
	int startY;
	int endX;
	int endY;
	public SimpleGridGraph iGraph;
	ViewAnalyserGrid viewAnalyser = new ViewAnalyserGrid();
	boolean[][] viewobstacles;
	boolean[][] viewAnalyse;
	Vector<Position> positions = new Vector<Position>();
	int[][] sumViews;
	DepthAnalyser2D depthAnalyser;
	int[][] traffic;
	Bounds2D bounds=new Bounds2D();
	
	Vector<Location>locations=new Vector<Location>();
	public void setup() {
		size(801, 636);
		dataImage = this.loadImage("analyseApplets/background.png");
		walkImage = this.loadImage("analyseApplets/backgroundWalk.png");
		//backgroundView=this.loadImage(selectInput());
		backgroundPos=this.loadImage("analyseApplets/backgroundPos.png");
		Boolean[][] depthGrid = new Boolean[dataImage.width][dataImage.height];
		traffic=new int[dataImage.width][dataImage.height];
		viewobstacles = new boolean[dataImage.width][dataImage.height];
		sumViews = new int[dataImage.width][dataImage.height];
		for (int x = 0; x < dataImage.width; x++) {
			for (int y = 0; y < dataImage.height; y++) {
				int c = dataImage.get(x, y);
				float brightness = brightness(c);
				if (brightness > 0.8) {
					depthGrid[x][y] = new Boolean(true);
					viewobstacles[x][y] = false;
					bounds.addPos2D(x,y);
				} else {
					viewobstacles[x][y] = true;
				}
			}
		}
		boolean[][] obstacles = new boolean[(int) dataImage.width][(int) dataImage.height];
		for (int x = 0; x < walkImage.width; x++) {
			for (int y = 0; y < walkImage.height; y++) {
				int c = walkImage.get(x, y);
				int r = (int) red(c);
				int g = (int) green(c);
				int b = (int) blue(c);
				if (r > 200 && g < 200 && b < 200) {
					startX = x;
					startY = y;
				}
				if (r < 200 && g > 200 && b < 200) {
					endX = x;
					endY = y;
				}
				float brightness = brightness(c);

				if (brightness > 0.8) {
					obstacles[x][y] = false;
				} else {
					obstacles[x][y] = true;
				}
			}
		}
		iGraph = new SimpleGridGraph(obstacles);
		/*for (int x = 0; x < backgroundView.width; x++) {
			for (int y = 0; y < backgroundView.height; y++) {
				int c = backgroundView.get(x, y);
				float brightness = brightness(c);
				if (brightness > 0.2&&viewobstacles[x][y]) {
					positions.add(new Position(x, y));
					
				}
			}
		}*/
		for (int x = 0; x < backgroundPos.width; x++) {
			for (int y = 0; y < backgroundPos.height; y++) {
				int c = backgroundPos.get(x, y);
				float red = red(c);
				float green = green(c);
				float blue = blue(c);
				if (red>200&&green<200&&blue<200) {
					Location location=new Location();
					location.x=x;
					location.y=y;
					location.iGraph=iGraph;
					location.locations=locations;
					location.traffic=traffic;
					location.setup();
					locations.add(location);
				}
			}
		}
		println("locations"+locations.size());
		rectMode(CENTER);
		depthAnalyser = new DepthAnalyser2D();
		depthAnalyser.calculateObjectDepth(depthGrid);

	}

	int iPos = 0;

	public void draw() {
		// image(dataImage,0,0);
		rectMode(CENTER);
		background(255);
		noStroke();
		//image(dataImage,0,0);
		for (int i=0;i<locations.size();i++){
			Location l=locations.get(i);
			for (int j=0;j<40;j++){
				l.walkPath();
			}
		}
		fill(0,255,0,100);
		float maxT=0;
		for (int x = 0; x < traffic.length; x++) {
			for (int y = 0; y < traffic[0].length; y++) {
				int t=traffic[x][y];
				if (t>maxT){
					maxT=t;
				}
			}
		}
		maxT=85;
		println("amxT: "+maxT);
		colorMode(HSB,255);
		for (int x = 0; x < traffic.length; x++) {
			for (int y = 0; y < traffic[0].length; y++) {
				int t=traffic[x][y];
				if (t>0){
					float cV=map(t,0,maxT,0,255);
					//rect(x,y,2,2);
					//set(x,y,color(0,255,0));
					set(x,y,color(cV,255,255));
				}
			}
		}
		//this.filter(this.BLUR, 1);
		for (int i=0;i<locations.size();i++){
			Location l=locations.get(i);
			int cX=iGraph.getX(l.iPos);
			int cY=iGraph.getY(l.iPos);
			set(cX,cY,color(0));
		}
		
		//this.bl
		//saveFrame("traffic2-####.png");
		if (frameCount>500){noLoop();}
		println("frameCount"+frameCount);
	}

	public void drawIsoView(){
		colorMode(HSB);
		int max = 1000;
		println(frameCount);
		if (frameCount > 50) {
			noLoop();
			//println("end");
		}
		for (int j=0;j<100;j++){
		
		int i = (int) random(positions.size());
		Position p = positions.get(i);
		positions.remove(i);
		boolean[][] views = viewAnalyser
				.getViewAnalyse(viewobstacles, p.x, p.y);
		for (int x = 0; x < views.length; x++) {
			for (int y = 0; y < views[0].length; y++) {
				int dX=x-p.x;
				int dY=y-p.y;
				float d=sqrt(dX*dX+dY*dY);
				if (d<100&&views[x][y]) {
					sumViews[x][y]++;
				}

			}
		}
		}
		for (int x = 0; x < sumViews.length; x++) {
			for (int y = 0; y < sumViews[0].length; y++) {
			
				int cValue = sumViews[x][y];
				
				int cCol = (int) map(cValue, 0, max, 0, 255);
				set(x, y, color(cCol, 255, 255));
				
			}
		}
		//saveFrame("isoView-####.png");
	}
	public void drawDepth() {
		int max = 40;
		colorMode(HSB, max);
		double[][] depth = depthAnalyser.getDepth();
		for (int x = 0; x < depth.length; x++) {
			for (int y = 0; y < depth[0].length; y++) {
				double d = depth[x][y];
				if (d > iPos) {

					set(x, y, color(max, 0, max));
				} else {
					set(x, y, color((float) d % max, max, max));
				}
			}
		}
		// println(iPos);
		iPos++;
		// saveFrame("depth-####.png");
		if (iPos >= 300) {
			noLoop();
		}
	}

	public void drawView() {
		int cI = path.get(iPos);
		int px = iGraph.getX(cI);
		int py = iGraph.getY(cI);
		boolean[][] views = viewAnalyser.getViewAnalyse(viewobstacles, px, py);
		for (int x = 0; x < views.length; x++) {
			for (int y = 0; y < views[0].length; y++) {
				if (views[x][y]) {
					set(x, y, color(0, 255, 0));
					sumViews[x][y]++;
				}
				int cValue = sumViews[x][y];
				int cCol = (int) map(cValue, 0, 250, 255, 0);
				set(x, y, color(cCol, 255, cCol));
			}
		}
		noStroke();
		fill(255, 0, 0);
		rect(px, py, 8, 8);
		iPos++;
		// saveFrame("viewAll-####.png");
		if (iPos >= path.size()) {
			noLoop();
		}
	}

	public void calculatePath(PImage dataImage) {
		boolean[][] obstacles = new boolean[(int) dataImage.width][(int) dataImage.height];
		for (int x = 0; x < dataImage.width; x++) {
			for (int y = 0; y < dataImage.height; y++) {
				int c = dataImage.get(x, y);
				int r = (int) red(c);
				int g = (int) green(c);
				int b = (int) blue(c);
				if (r > 200 && g < 200 && b < 200) {
					startX = x;
					startY = y;
				}
				if (r < 200 && g > 200 && b < 200) {
					endX = x;
					endY = y;
				}
				float brightness = brightness(c);

				if (brightness > 0.8) {
					obstacles[x][y] = false;
				} else {
					obstacles[x][y] = true;
				}
			}
		}
		iGraph = new SimpleGridGraph(obstacles);

		int startI = iGraph.getIndex(startX, startY);
		int endI = iGraph.getIndex(endX, endY);
		dijkstra = new Dijkstra(iGraph, startI);
		path = dijkstra.getShortestPath(endI);

		// return analyseImage;
	}
}

class Position {
	int x;
	int y;

	Position() {

	}
	Position(int x, int y) {
		this.x = x;
		this.y = y;
	}
}

class Location{
	int x;
	int y;
	int iPos;
	int iGoal;
	Dijkstra dijkstra;
	SimpleGridGraph iGraph;
	Vector<Location>locations;
	int[][] traffic;
	public void setup(){
		iPos = iGraph.getIndex(x, y);
		dijkstra = new Dijkstra(iGraph, iPos);
	}
	
	public void walkPath(){
		iPos=dijkstra.getPredecessor(iPos);
		if (iPos<0){
			Location newL=locations.get((int)(Math.random()*locations.size()));
			iPos=iGraph.getIndex(newL.x,newL.y);
		}
		if (Math.random()>0.2f){
		Vector<Integer>nbs=iGraph.get8Nbs(iPos);
		iPos=nbs.get((int)(Math.random()*nbs.size()));
		}
		int cX=iGraph.getX(iPos);
		int cY=iGraph.getY(iPos);
		traffic[cX][cY]++;
	}
	
}